import Food from './Food'
import Score from './Score'

class Snake {
	head: HTMLDivElement
	bodies: HTMLCollection
	snake: HTMLDivElement
	/**
	 * 构造函数
	 */
	constructor() {
		// 获取头部元素
		this.head = <HTMLDivElement>document.querySelector('.snake > div')
		// 获取蛇身元素
		this.snake = <HTMLDivElement>document.querySelector('.snake')
		// 获取蛇身的子元素
		this.bodies = this.snake.getElementsByTagName('div')
	}

	/**
	 * 获取蛇头的横坐标
	 * @returns 蛇头的横坐标
	 */
	get X(): number {
		return this.head.offsetLeft
	}

	/**
	 * 获取蛇头的纵坐标
	 * @returns 蛇头的纵坐标
	 */
	get Y(): number {
		return this.head.offsetTop
	}

	set X(x: number) {
		if (this.X == x) {
			return
		}
		if (x < 0 || x > 600) {
			throw new Error('撞到墙了，游戏结束')
		}
		// 先移动蛇的身体 蛇头最后移动
		this.move()
		this.head.style.left = x + 'px'
		// 检查一下蛇是否撞到了自己的身体
		this.checkHeadBody()
	}

	set Y(y: number) {
		console.log('Y set ', y)
		if (this.Y == y) {
			return
		}
		if (y < 0 || y > 600) {
			throw new Error('撞到墙了，游戏结束')
		}
		// 先移动蛇的身体 蛇头最后移动
		this.move()
		this.head.style.top = y + 'px'
		// 检查一下蛇是否撞到了自己的身体
		this.checkHeadBody()
	}

	/**
	 * 检查头部和身体是否相撞
	 */
	checkHeadBody() {
		for (let index = 1; index < this.bodies.length; index++) {
			let x = (this.bodies[index] as HTMLDivElement).offsetLeft // 获取当前元素的左侧距离
			let y = (this.bodies[index] as HTMLDivElement).offsetTop // 获取当前元素的顶部距离

			if (x == this.X && y == this.Y) {
				// 判断是否与自己相撞
				throw new Error('撞到自己了，游戏结束')
			}
		}
	}

	/**
	 * 移动蛇的身体
	 */
	move() {
		for (let index = this.bodies.length - 1; index > 0; index--) {
			let x = (this.bodies[index - 1] as HTMLDivElement).offsetLeft
			let y = (this.bodies[index - 1] as HTMLDivElement).offsetTop

			;(this.bodies[index] as HTMLDivElement).style.left = x + 'px'
			;(this.bodies[index] as HTMLDivElement).style.top = y + 'px'
		}
	}

	moveDirection(direction: number, food: Food, score: Score) {
		switch (direction) {
			case 37://向左
				this.X -= 20
				break
			case 38://向上
				this.Y -= 20
				break
			case 39://向右
				this.X += 20
				break
			case 40://向下
				this.Y += 20
				break
		}
		// 检测蛇是否吃到了食物
		this.eatFood(food, score)
	}

	/**
	 * 添加蛇身体
	 */
	addBody() {
		// 创建一个div元素作为蛇身体
		let body = document.createElement('div')
		// 设置新创建的蛇身体与最后一个蛇身体的left和top样式相同
		body.style.left = (this.bodies[this.bodies.length - 1] as HTMLDivElement).offsetLeft + 'px'
		body.style.top = (this.bodies[this.bodies.length - 1] as HTMLDivElement).offsetTop + 'px'
		// console.log(`x=${(this.bodies[this.bodies.length - 1] as HTMLDivElement).style.left},y=${(this.bodies[this.bodies.length - 1] as HTMLDivElement).style.top}`)
		// 将新创建的蛇身体添加到蛇的子元素中
		this.snake.appendChild(body)
		// 更新蛇身体的数组
		this.bodies = this.snake.getElementsByTagName('div')
	}

	/**
	 * 吃到食物
	 * @param food 食物对象
	 */
	eatFood(food: Food, score: Score) {
		// 如果蛇头的位置与食物的位置相同
		if (this.X == food.X && this.Y == food.Y) {
			// 吃到了食物，更新食物的位置
			food.change()
			// 蛇身加长
			this.addBody()
			// 增加分数
			score.addSocre()
		}
	}
}

/**
 * 导出默认的 Snake 类
 */
export default Snake
